#!/usr/bin/python

import sys, PyKDGantt
from PyQt4 import QtGui, QtCore

class Node:
	def __init__(self,  name):
		self.name = name
		self.children = []
		self.parent 	= None
		self.tpe   		= PyKDGantt.TypeTask
		self.start_date = QtCore.QDateTime( QtCore.QDate().currentDate() )
		self.end_date   = QtCore.QDateTime( QtCore.QDate().currentDate().addDays(4) )
		self.completion = 50
		
	def getParent(self):
		return self.parent
		
	def setParent(self , p):
		self.parent = p
		
	def getType(self):
		return self.tpe
		
	def setType(self,tpe):
		self.tpe = tpe
		
	def childCount(self):
		return len(self.children)
		
	def setStartDate(self, date):
		self.start_date = date
	
	def setEndDate(self, date):
		self.end_date = date
		
	def setCompletion(self, comp):
		self.completion = comp
	
	def addChild(self, child):
		child.parent = self
		self.children.append(child)
		
	def hasParent(self):
		return self.parent != None
		
	def child(self,nr):
		if nr >= self.childCount():
			print "Error accessing child idx (Node class)"
			return None
		return self.children[nr]
		
	def childIdx(self, ch):
		return self.children.index(ch)

class ItemTypeComboBox( QtGui.QComboBox ):
	def __init__(self, parent):
		super(ItemTypeComboBox,self).__init__(parent)
		self.addItem( "Event", QtCore.QVariant( PyKDGantt.TypeEvent ) )
		self.addItem( "Task", QtCore. QVariant( PyKDGantt.TypeTask ) )
		self.addItem( "Summary", QtCore.QVariant( PyKDGantt.TypeSummary ) )

	def itemType(self):
		return self.itemData( self.currentIndex() ).toInt()[0]

	def setItemType(self, it):
		self.setCurrentIndex( it - 1 )
		

class ComboItemDelegate( PyKDGantt.ItemDelegate ):
	def __init__(self):
		super(ComboItemDelegate,self).__init__()
		
	def createEditor( self, parent, option, idx ):
		if idx.isValid() and idx.column() == 1:
			return ItemTypeComboBox(parent)
			
		return PyKDGantt.ItemDelegate.createEditor( parent, option, idx )
		
	def setEditorData ( self, editor, index ):
		if issubclass(ItemTypeComboBox, editor.__class__) and index.isValid():
			editor.setItemType( index.data(QtCore.Qt.EditRole).toInt()[0] )
		else:
			PyKDGantt.ItemDelegate.setEditorData(edito, index)
			
	def setModelData ( self, editor, model, index ):
		if issubclass(ItemTypeComboBox, editor.__class__) and index.isValid():
			model.setData(index, QtCore.QVariant( editor.itemType() ))
		else:
			PyKDGantt.ItemDelegate.setModelData(editor,model,index)
			
	def drawDisplay( self, painter, option, rect, text ):
		typ = text.toInt()[0]
		str = "None"
		
		if typ == PyKDGantt.TypeTask: str = "Task"
		if typ == PyKDGantt.TypeEvent: str = "Event"
		if typ == PyKDGantt.TypeSummary: str = "Summary"
		
		PyKDGantt.ItemDelegate.drawDisplay( self, painter,option,rect,str )
	
class ItemModel( QtCore.QAbstractItemModel ):
	def __init__(self):
		super(ItemModel,self).__init__()
		node = Node("ROOT")
		self.root = node
		
	def addNode(self, node, parent = None):

		if parent != None:
			parent.addChild(node)
		else:
			self.root.addChild(node)
			
		self.emit ( QtCore.SIGNAL( "layoutChanged ()" ) )
		
	def index( self, row, col, parent = QtCore.QModelIndex()):
		if parent.isValid():
			node = parent.internalPointer()
		else:
		 	node = self.root

		if row >= node.childCount() or row < 0:
			return QtCore.QModelIndex()
		
		modidx = self.createIndex( row, col, node.child(row) )
		return modidx


	def parent( self, idx ):
		if not idx.isValid():
			return QtCore.QModelIndex()
		
		n = idx.internalPointer()
		
		p = n.getParent()
		
		if p == self.root:
			return QtCore.QModelIndex()
			
		pp = p.getParent()
		
		return self.createIndex( pp.childIdx(p), 0, p)

	
	def rowCount( self, idx ):
		if not idx.isValid():
			return self.root.childCount()
		return idx.internalPointer().childCount()

	def columnCount( self, idx ):
		return 5

		
	def headerData( self, section, orientation, role = QtCore.Qt.DisplayRole ):
		if orientation != QtCore.Qt.Horizontal or role != QtCore.Qt.DisplayRole :
			return QtCore.QVariant() 
			
		if   section == 0: return  "Name" 
		elif section == 4: return  "Completion %" 
		elif section == 2: return  "Start date" 
		elif section == 3: return  "End date"
		elif section == 1: return  "Type" 
		
		return QtCore.QVariant()

	def data( self, idx, role = QtCore.Qt.DisplayRole ):
		if not idx.isValid():
			return QtCore.QVariant()
		
		pntr = idx.internalPointer()

		if idx.column() == 0:
			if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				return pntr.name
			elif role == PyKDGantt.TextPositionRole:
				return PyKDGantt.StyleOptionGanttItem.Center

		elif idx.column() == 1:
			if role ==  QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				return pntr.getType()
		
		elif idx.column() == 2:
			if role == QtCore.Qt.DisplayRole:
				return pntr.start_date.date().toString("dd-MM-yyyy")
		
			elif role ==  PyKDGantt.StartTimeRole or role == QtCore.Qt.EditRole:
				return pntr.start_date

		elif idx.column() == 3:
			if role == QtCore.Qt.DisplayRole:
				return QtCore.QString( pntr.end_date.date().toString("dd-MM-yyyy") )

			elif role ==  PyKDGantt.EndTimeRole or role == QtCore.Qt.EditRole:
				return pntr.end_date

		elif idx.column() == 4:
			if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				return int(pntr.completion)
			
		elif idx.column() == 5:
			if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				return QtCore.QString(pntr.name)
				
			elif role == PyKDGantt.StartTimeRole:
				return QtCore.QDateTime(pntr.start_date)
				
			elif role == PyKDGantt.EndTimeRole:
				return QtCore.QDateTime(pntr.end_date)
				
			elif role == PyKDGantt.TaskCompletionRole:
				return int(pntr.completion)
				
			elif role == PyKDGantt.ItemType:
				return int(pntr.getType())

		return QtCore.QVariant()
	
	def setData( self, idx, value,role = QtCore.Qt.DisplayRole):
		if not idx.isValid():
			return False

			
		n = idx.internalPointer()
		
		if idx.column() == 0:
			if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				n.name = value.toString()
				self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)" ), idx, idx  )
				
			if role == PyKDGantt.TextPositionRole:
				self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)" ), idx, idx  )

		if idx.column() == 1:
			if role == QtCore.Qt.DisplayRole  or role == QtCore.Qt.EditRole:
				n.setType( value.toInt()[0] )
				self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)" ), idx, idx  )

		if idx.column() == 2:
			 if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole or PyKDGantt.StartTimeRole:
			 	n.setStartDate( value.toDateTime() )
			 	self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)" ), idx, idx  )
			 	
		if idx.column() == 3:
			 if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole or PyKDGantt.EndTimeRole:
			 	n.setEndDate( value.toDateTime() )
			 	self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)"), idx, idx  )

		if idx.column() == 4:
			if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
				n.setCompletion( value.toInt()[0] )
				self.emit ( QtCore.SIGNAL( "dataChanged(QModelIndex, QModelIndex)" ), idx, idx  )

		return True
		
	def flags( self, idx ):
		if not idx.isValid():
			return QtCore.Qt.NoItemFlags
			
		flags = QtCore.QAbstractItemModel.flags( self, idx ) | QtCore.Qt.ItemIsEditable
		return flags
		
		
		
class Graphics( PyKDGantt.GraphicsView ):
	def __init__(self):
		super(Graphics,self).__init__()
		
	def wheelEvent ( self, event ):
		event.accept()
		grid = self.grid() 
		
		if grid.dayWidth() < 20.0 and event.delta() < 0:
			return
			
		
		grid.setDayWidth( grid.dayWidth() + event.delta() * .02 )


class Gantt( PyKDGantt.View ):
	def __init__(self):
		PyKDGantt.View.__init__(self)

		node1 = Node("Test1")
		node2 = Node("Test2")
		node3 = Node("Test3")
		node4 = Node("Test4")
		
		self.graphics = Graphics()
		self.setGraphicsView(self.graphics)
		
		self.constModel = PyKDGantt.ConstraintModel(self)
		self.setConstraintModel(self.constModel)
		
		self.itemModel = ItemModel()

		self.itemModel.addNode(node1)
		self.itemModel.addNode(node2)
		self.itemModel.addNode(node3)
		self.itemModel.addNode(node4, node3)
		
		self.selModel = QtGui.QItemSelectionModel(self.itemModel)
				
		self.datetimegrid = PyKDGantt.DateTimeGrid()
		
		self.datetimegrid.setStartDateTime( QtCore.QDateTime( QtCore.QDate().currentDate() ) )
		self.datetimegrid.setDayWidth(20)
		self.setGrid(self.datetimegrid)
		self.setModel(self.itemModel)
		
	
		self.connect( self.constraintModel(), QtCore.SIGNAL( "pyConstraintAdded(Constraint)" ), self.constraintAdded )
		self.connect( self.constraintModel(), QtCore.SIGNAL( "pyConstraintRemoved(Constraint)" ), self.constraintAdded )
		self.connect( self.datetimegrid, QtCore.SIGNAL( "gridChanged()" ), self.gridChanged )
		
		self.setSelectionModel( self.selModel )
		
		self.comboDelegate = ComboItemDelegate()
		self.leftView().setItemDelegateForColumn( 1, self.comboDelegate )		
	
	# Here we've got slot to manage constraints
	def constraintAdded(self, c):
		print c.startIndex().internalPointer().name
		print c.endIndex().internalPointer().name
		pass
		
	def gridChanged(self):
		pass
		
app = QtGui.QApplication(sys.argv)


# Set style to DwarfLabs internals color palette
palette = QtGui.QPalette(QtGui.QColor(75,75,75))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Window,QtGui.QColor(60,60,60))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Base,QtGui.QColor(40,40,40))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.WindowText,QtGui.QColor(255,255,255))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Text,QtGui.QColor(230,230,230))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Button,QtGui.QColor(80,80,80))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.BrightText,QtGui.QColor(255,255,255))
palette.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Background,QtGui.QColor(70,70,70))
app.setStyle("plastique")
app.setPalette(palette)

gantt = Gantt()

gantt.show()

app.exec_()

